$.widget("vg.MasterDetail", {
    options: {
        saveButtonClass: 'action-save',
        cancelButtonClass: 'action-cancel',
        saveButtonId: 'save',
        cancelButtonId: 'cancel',
        createButtonId: 'create',
        createPlaceholderId: 'createPlaceholder',
        masterTableId: 'masterTable',
        masterTable: null,
        detailTemplateId: 'detailTemplate',
        masterFilter: true,
        masterPaginate: true,
        masterInfo: true,
        masterData: null,
        masterAjaxSource: null,
        selectedRowClass: 'selected',
        visitedRowClass: 'visited',
        initDetail: function() {
        },
        updateDetail: function() {
        },
        createDetail: function() {
        },
        validateDetail: function() {
            return true;
        },
        masterDrawCallback: function() {
        },
        openDetailCallback: function() {
        }
    },

    _form_modified: false,

    _addRowClass: function(row, newClass) {
        // Add Class to multiple rows
        var md = this;
        var nextRow = $(row).next();

        $(row).addClass(newClass);

        while (nextRow) {
            if (nextRow.hasClass('countme-in')) {
                $(nextRow).addClass(newClass);
                nextRow = $(nextRow).next();
            } else {
                nextRow = null;
            }
        }
    },

    _toggleRowClass: function(row, newClass) {
        // Toggle Class on multiple rows
        var md = this;
        var nextRow = $(row).next();

        $(row).toggleClass(newClass);

        while (nextRow) {
            if (nextRow.hasClass('countme-in')) {
                $(nextRow).toggleClass(newClass);
                nextRow = $(nextRow).next();
            } else {
                nextRow = null;
            }
        }
    },

    _itemModified: function(row, container) {
        // When item data is modified, show alert and enable save button.
        // Disable close
        var md = this;
        md._form_modified = true;

        $('.unmodified', container).toggleClass('unmodified modified');
        $('.actions-item .btn-primary', container).removeAttr('disabled');
        $('.closeable', container).unbind();
        $('.closeable', container).removeClass('closeable');

        var saveButtons = $('.' + md.options.saveButtonClass, container);

        saveButtons.unbind('click');
        saveButtons.click(function() {
            if (row === null) {
                md._createDetail(md._createPlaceholder);
            } else {
                md._updateDetail(container, row);                
            }
        });
    },

    _listenFormChanges: function(row, container) {
        // Adds listeners to input, textareas. Add listen-click or -change to other elements you want to observe
        var md = this;
        $('.listen-change', container).on('change', function() {
            md._itemModified(row, container);
        });

        $('.listen-click', container).on('click', function() {
            md._itemModified(row, container);
        });

        $('input', container).on('change keypress paste', function() {
            md._itemModified(row, container);
        });

        $('textarea', container).on('change keypress paste', function() {
            md._itemModified(row, container);
        });

        $('.datepicker', container).datepicker()
                .on('changeDate', function(e) {
                    md._itemModified(row, container);
                });
    },

    _create: function() {
        var md = this;
        console.log('MasterDetail constructor');
        console.log(this.options);

        md._masterTable = md.options.masterTable ? md.options.masterTable : $('#' + md.options.masterTableId);
        md._detailTemplate = $('#' + md.options.detailTemplateId);
        md._createPlaceholder = $('#' + md.options.createPlaceholderId);
        md._createButton = $('#' + md.options.createButtonId);

        md._createOpen = false;

        md._masterDataTable = md._masterTable.dataTable({
            aoColumns: md.options.masterColumns,
            bDeferRender: true,
            bFilter: md.options.masterFilter,
            bInfo: md.options.masterInfo,
            bPaginate: md.options.masterPaginate,
            bDestroy: true,
            iDisplayLength: $.cookie('table_length', Number),
            aaData: md.options.masterData,
            sAjaxSource: md.options.masterAjaxSource,
            sAjaxDataProp: '',
            fnCreatedRow: function(row, data, dataIndex) {
                $(row).unbind('click').bind('click', function() {
                    // This is where we do the get that fails
                    var freshData = md._masterTable.fnGetData(row);
                    md._toggleUpdateDetail(row, freshData);
                });

                $('.listen-click', row).on('click', function() {
                    md._itemModified(row, row);
                });
            },
            // Add tool tips to span's that are wider than their cell
            // Note that custom styling to the table is necessary for this to happen
            fnDrawCallback: function(asettings) {
                var dt = this;
                $('td', dt.fnGetNodes()).each(function() {
                    var td = $(this);
                    var span = td.find('span');
                    if (span !== null && span.width() > td.width()) {
                        span.attr('title', span.text());
                    }
                });
                $(dt.fnGetNodes()).css('cursor', 'pointer');
                md.options.masterDrawCallback(dt);
            }
        });

        var lengthSelect = $('select[name="' + md.options.masterTableId + '_length"]');
        lengthSelect.change(function() {
            console.log('Updating table length cookie (value=' + lengthSelect.val() + ')');
            $.cookie('table_length', lengthSelect.val(), {expires: 365, path: '/'});
        });

        md._createButton.click(function() {
            md.toggleCreateDetail();
        });
    },

    _toggleUpdateDetail: function(row, data) {
        var md = this;

        md._toggleRowClass(row, md.options.selectedRowClass);

        if (md._masterDataTable.fnIsOpen(row)) {
            md._masterDataTable.fnClose(row);
            $('.' + md.options.visitedRowClass).removeClass(md.options.visitedRowClass);

            md._addRowClass(row, md.options.visitedRowClass);

            $('td:first', row).attr("tabindex", "999");
            $('td:first', row).focus();
            $('td:first', row).removeAttr("tabindex");
            return;
        } else {
            $('.' + md.options.visitedRowClass).removeClass(md.options.visitedRowClass);
        }
        // info_row is the style class of the container td element
        var container = md._masterDataTable.fnOpen(row, md._detailTemplate.html(), "info_row");
        md.options.openDetailCallback(md._masterDataTable, row, container);

        console.log("Initializing update detail view");
        md.options.initDetail(container, data);

        var cancelButtons = $('.' + this.options.cancelButtonClass, container);

        $('.closeable', container).click(function() {
            md._toggleUpdateDetail(row);
        });

        cancelButtons.click(function() {
            md._toggleUpdateDetail(row);
        });

        // Listen to click and changes in form and activate save row
        md._listenFormChanges(row, container);
    },

    toggleCreateDetail: function() {
        var md = this;
        $('.info_row').toggleClass('hidden');
        $('.info_row').toggleClass('unmodified modified');

        if (md._createOpen) {
            // Dubious if this is user friendly - edit might be in progress...
            md._createPlaceholder.empty();
            md._createOpen = false;
            return;
        }
        md._createPlaceholder.append(md._detailTemplate.html());
        md._createOpen = true;

        console.log("Initializing create detail view");
        md.options.initDetail(md._createPlaceholder, null);

        var cancelButtons = $('.' + md.options.cancelButtonClass, md._createPlaceholder);
        cancelButtons.click(function() {
            md.toggleCreateDetail();
        });

        // Listen to click and changes in form and activate save
        md._listenFormChanges(null, $('.info_row'));
    },

    _updateDetail: function(container, row) {
        var md = this;
        console.log("updateDetail()");
        if (md.options.validateDetail(container)) {
           var data = md.options.updateDetail(container);
            if (data) {
                md._masterDataTable.fnUpdate(data, row);
            }
            if (data !== false) {
                md._toggleUpdateDetail(row);
            } 
        } 
    },

    _createDetail: function(container) {
        var md = this;
        console.log("createDetail()");
        if (md.options.validateDetail(container)) {
            var data = md.options.createDetail(container);
            if (data) {
                md._masterDataTable.fnAddData(data);
            }
            if (data !== false) {
                md.toggleCreateDetail();
            }
        }
    }
});

var MasterDetail = {
    renderLink: function(data, type, full) {
        return MasterDetail.renderString('<a class="update-action update-edit">' + data + '</a>', type, full);
    },

    renderString: function(data, type, full) {
        return (!data || data === '') ? '-' : '<span>' + data + '</span>';
    },

    renderDate: function(data, type, full) {
        return data ? $.datepicker.formatDate('yy-mm-dd', new Date(data)) : '-';
    },

    renderYesNo: function(data, type, full) {
        return data === true ? 'Ja' : 'Nej';
    },

    renderActiveNoActive: function(data, type, full) {
        return data === 'ACTIVE' ? 'Aktiv' : 'Inaktiv';
    },

    renderClosable: function(data, type, full) {
        return (!data || data === '') ? '-' : '<i class="icon-check-minus"></i><span class="h2">' + data + '</span>';
    }
};
